package io.itit.ecp.admin.provide.action.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.itit.ecp.admin.common.constants.ParamConstants;
import io.itit.ecp.admin.common.enums.IMeterDeviceEnums;
import io.itit.ecp.admin.common.enums.StatisticsModeEnums;
import io.itit.ecp.admin.provide.action.req.CompanyMeterStatisticQueryReq;
import io.itit.ecp.admin.provide.action.resp.CompanyMeterStaticsDetailRes;
import io.itit.ecp.admin.provide.action.resp.CompanyMeterStatisticsResp;
import io.itit.ecp.admin.provide.filter.IEnergyDataFilter;
import io.itit.ecp.admin.server.entity.*;
import io.itit.ecp.admin.server.entity.extend.EnergyDataExtEntity;
import io.itit.ecp.admin.server.service.*;
import io.itit.grass.common.provide.action.resp.ResultResp;
import io.itit.grass.common.provide.action.validation.IExport;
import io.itit.grass.common.provide.action.validation.IQueryPage;
import io.itit.grass.common.provide.utils.ParamUtils;
import io.itit.grass.common.server.dto.ParamDto;
import io.itit.grass.common.server.utils.ConvertUtils;
import io.itit.grass.estelle.starter.core.ExcelXSSFUtil;
import io.itit.grass.estelle.starter.util.JsonUtil;
import io.itit.grass.web.wall.utils.PageUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * @Author：Roy
 * @Description：公司统计控制类
 * @Date：Create by 2023-12-05 11:48:22
 */
@Api(tags = "公司计量统计")
@RestController
@RequestMapping("/ecp-admin/companyMeterStatistic")
public class CompanyMeterStatisticController {

    @Resource
    private IEnergyDataService energyDataService;

    @Resource
    private ISceneCompanyService sceneCompanyService;

    @Resource
    private ISceneProjectService sceneProjectService;

    @Resource
    private ISceneRoomService sceneRoomService;


    @Resource
    private ISceneFloorService sceneFloorService;

    @Resource
    private ISceneEdificeService sceneEdificeService;

    @Resource
    private IMeterDeviceService meterDeviceService;

    @Resource
    private IEnergyConsumptionTypeService energyConsumptionTypeService;

    @ApiOperation("公司计量统计分页查询")
    @PostMapping("queryPage")
    @RequiresPermissions("ecp-admin:companyMeterStatistic:search")
    public ResultResp<IPage<CompanyMeterStatisticsResp>> queryPage(@RequestBody @Validated(IQueryPage.class) CompanyMeterStatisticQueryReq req) {
        ParamDto paramDto = ParamUtils.paramDto(req);
        if (!"hour".equals(req.getStatisticsMode())) {
            paramDto.add(ParamConstants.MYSQL_DATE_FORMAT, StatisticsModeEnums.mysqlDateFormat(req.getStatisticsMode()));
        } else {
            paramDto.add(ParamConstants.MYSQL_DATE_FORMAT, "%Y-%m-%d %H:%m");
        }
        IPage<CompanyMeterStatisticsResp> page = ConvertUtils.convert(energyDataService.companyMeterStatistics(paramDto,
                PageUtils.getPage(req, EnergyDataExtEntity.class)), CompanyMeterStatisticsResp.class);
        return ResultResp.success(page);
    }

    public static String getRoomInfo(MeterDeviceEntity meterDevice, List<SceneRoomEntity> roomList, List<SceneFloorEntity> floorEntities, List<SceneEdificeEntity> edificeEntities) {
        String result = "";
        if (StringUtils.isNotEmpty(meterDevice.getSceneEdificeId())) {
            result += edificeEntities.stream().filter(item -> StringUtils.equals(item.getId(), meterDevice.getSceneEdificeId()))
                    .findFirst()
                    .map(SceneEdificeEntity::getEdificeName).orElse("");
        }
        if (StringUtils.isNotEmpty(meterDevice.getSceneFloorId())) {
            result += floorEntities.stream().filter(item -> StringUtils.equals(item.getId(), meterDevice.getSceneFloorId()))
                    .findFirst()
                    .map(SceneFloorEntity::getFloorName).orElse("");
        }
        if (StringUtils.isNotEmpty(meterDevice.getSceneRoomId())) {
            result += roomList.stream().filter(item -> StringUtils.equals(item.getId(), meterDevice.getSceneRoomId()))
                    .findFirst()
                    .map(SceneRoomEntity::getRoomName).orElse("");
        }
        return result;
    }

    @ApiOperation("详情")
    @GetMapping("detail")
    public ResultResp<CompanyMeterStaticsDetailRes> detail(@RequestParam String ids,
                                                           @RequestParam String sceneCompanyId,
                                                           @RequestParam String energyTypeId,
                                                           String solidifyDate) throws Exception {
        List<EnergyDataEntity> energyDataEntities = energyDataService.listByIds(Arrays.stream(StringUtils.split(ids, ",")).collect(Collectors.toSet()));
        SceneCompanyEntity companyEntity = sceneCompanyService.getById(sceneCompanyId);
        EnergyConsumptionTypeEntity energyConsumptionType = energyConsumptionTypeService.getById(energyTypeId);
        CompanyMeterStaticsDetailRes result = new CompanyMeterStaticsDetailRes();
        result.setId(companyEntity.getId());
        result.setCompanyName(companyEntity.getCompanyName());
        result.setStaticsTime(DateUtils.parseDate(solidifyDate, "yyyy-MM-dd HH", "yyyy-MM-dd HH:mm", "yyyy/MM/dd", "yyyy/MM", "yyyy"));
        result.setSceneProjectId(companyEntity.getSceneProjectId());
        SceneProjectEntity projectEntity = sceneProjectService.getById(companyEntity.getSceneProjectId());
        result.setSceneProjectName(Objects.isNull(projectEntity) ? null : projectEntity.getProjectName());
        List<SceneRoomEntity> roomList = sceneRoomService.list(new LambdaQueryWrapper<SceneRoomEntity>()
                .eq(SceneRoomEntity::getSceneCompanyId, companyEntity.getId()));
        Set<String> floorIds = roomList.stream()
                .map(SceneRoomEntity::getSceneFloorId)
                .filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        List<CompanyMeterStaticsDetailRes.MeterDeviceDetail> list = Collections.emptyList();
        if (!floorIds.isEmpty()) {
            List<SceneFloorEntity> floorEntities = sceneFloorService.list(new LambdaQueryWrapper<SceneFloorEntity>().in(SceneFloorEntity::getId, floorIds));
            Set<String> edificeIds = roomList.stream()
                    .map(SceneRoomEntity::getSceneEdificeId)
                    .filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
            List<SceneEdificeEntity> edificeEntities = sceneEdificeService.list(new LambdaQueryWrapper<SceneEdificeEntity>().in(SceneEdificeEntity::getId, edificeIds));
            String roomInfo = roomList.stream().map(item -> {
                String edificeName = edificeEntities.stream().filter(edifice -> StringUtils.equals(edifice.getId(), item.getSceneEdificeId()))
                        .findFirst().map(SceneEdificeEntity::getEdificeName).orElse("");

                String floorName = floorEntities.stream().filter(edifice -> StringUtils.equals(edifice.getId(), item.getSceneFloorId()))
                        .findFirst().map(SceneFloorEntity::getFloorName).orElse("");
                return edificeName + floorName + item.getRoomName();
            }).collect(Collectors.joining("、"));
            result.setRoomInfo(roomInfo);
            Set<String> meterIds = energyDataEntities.stream().map(EnergyDataEntity::getMeterDeviceId).collect(Collectors.toSet());
            List<MeterDeviceEntity> meterDeviceEntities = CollectionUtils.isEmpty(meterIds) ? Collections.emptyList() :
                    meterDeviceService.list(new LambdaQueryWrapper<MeterDeviceEntity>()
                            .in(MeterDeviceEntity::getId, meterIds)
                            .in(MeterDeviceEntity::getEnergyTypeId, energyTypeId)
                            .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                    );
            list = meterDeviceEntities.stream().map(item -> {
                        CompanyMeterStaticsDetailRes.MeterDeviceDetail meterDeviceDetail = new CompanyMeterStaticsDetailRes.MeterDeviceDetail()
                                .setDeviceCode(item.getDeviceCode())
                                .setRoomInfo(getRoomInfo(item, roomList, floorEntities, edificeEntities))
                                .setDeviceName(item.getDeviceName())
                                .setIsFocus(item.getIsFocus())
                                .setReadMeterTag(item.getReadMeterTag());
                        List<EnergyDataEntity> dataEntities = energyDataEntities.stream()
                                .filter(energyData -> StringUtils.equals(energyData.getMeterDeviceId(), item.getId()))
                                .collect(Collectors.toList());
                        Date staticsDate = CollectionUtils.isEmpty(dataEntities) ? result.getStaticsTime() : dataEntities.get(0).getSolidifyDate();
                        meterDeviceDetail.setDateTime(staticsDate);
                        meterDeviceDetail.setValue(dataEntities.stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add));
                        meterDeviceDetail.setUnit(Objects.isNull(energyConsumptionType) ? null : energyConsumptionType.getEnergyUnit());
                        return meterDeviceDetail;
                    }

            ).collect(Collectors.toList());
        }
        result.setMeterDeviceDetails(list);
        return ResultResp.success(result);
    }

    @ApiOperation("导出")
    @PostMapping("export")
    @RequiresPermissions("ecp-admin:companyMeterStatistic:export")
    public void export(@RequestBody @Validated(IExport.class) CompanyMeterStatisticQueryReq req, HttpServletResponse response) {
        ParamDto paramDto = ParamUtils.paramDto(req);
        if (!"hour".equals(req.getStatisticsMode())) {
            paramDto.add(ParamConstants.MYSQL_DATE_FORMAT, StatisticsModeEnums.mysqlDateFormat(req.getStatisticsMode()));
        } else {
            paramDto.add(ParamConstants.MYSQL_DATE_FORMAT, "%Y-%m-%d %H:%m");
        }
        List<CompanyMeterStatisticsResp> list = ConvertUtils.convert(energyDataService.companyMeterExport(paramDto), CompanyMeterStatisticsResp.class);
        ExcelXSSFUtil.export("CompanyMeterStatisticsExport", JsonUtil.toJson(list, new IEnergyDataFilter.EnergyDataExtExportFilter()), response);
    }


}
